﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using KPIS.GERP.Models;
using KPIS.GERP.Models.HRM;
using KPIS.GERP.Models.SYS;
using KPIS.GERP.Models.SYS.ViewModel;

namespace KPIS.GERP.WCF.SYS
{
    public partial class SysApprovalService : ISysApprovalService
    {
        public GetAppPrcIdVM GetAppPrcId(GetAppPrcIdVM model)
        {
            using (var db = new GERPContext(true))
            {
                var appPrcGrp = db.ApproveProcessGroups.First(o => o.AppPrcGrpId == model.AppPrcGrpId);
                appPrcGrp.LoadMoreInformation();
                model.AppPrcId = appPrcGrp.Entities.First(o => o.Id == model.RefId).AppPrcId;
            }
            return model;
        }

        public IEnumerable<ApproveProcessGroup> SelectApproveProcessGroup()
        {
            using (var db = new GERPContext())
            {
                var approveProcessGroups = db.ApproveProcessGroups.ToList();
                var approveProcesses = db.ApproveProcesses.ToList();
                foreach (var approveProcessGroup in approveProcessGroups)
                {
                    approveProcessGroup.ApproveProcesses = approveProcesses.Where(o => o.AppPrcGrpId == approveProcessGroup.AppPrcGrpId).ToList();
                    if (approveProcessGroup.ApproveProcesses == null || approveProcessGroup.ApproveProcesses.Count == 0) continue;
                    foreach (var approveProcess in approveProcessGroup.ApproveProcesses)
                    {
                        approveProcess.ApproveProcessGroup = null;
                    }
                }
                return approveProcessGroups;
            }
        }

        public IEnumerable<ApproveProcess> SelectApproveProcess(int appPrcGrpEnum)
        {
            using (var db = new GERPContext())
            {
                var approveProcesses = appPrcGrpEnum != 0
                                           ? db.ApproveProcesses.Include(o => o.ApproveProcessGroup).Where(o => o.AppPrcGrpId == (int) appPrcGrpEnum).
                                                 ToList()
                                           : db.ApproveProcesses.Include(o => o.ApproveProcessGroup).ToList();
                foreach (var approveProcess in approveProcesses)
                {
                    if (approveProcess.ApproveProcessGroup == null) continue;
                    approveProcess.ApproveProcessGroup.ApproveProcesses = null;
                }
                return approveProcesses;
            }
        }

        public IEnumerable<ApprovePath> SelectApprovePath()
        {
            using (var db = new GERPContext())
            {
                var approvePaths = db.ApprovePaths.ToList();
                return approvePaths;
            }
        }

        public IEnumerable<ExecPosGroup> SelectExecPosGroup()
        {
            using (var db = new GERPContext())
            {
                var execPosGroups = db.ExecPosGroups.ToList();
                foreach (var execPosGroup in execPosGroups)
                {
                    if (execPosGroup.ExecPosGroupDtlses == null) continue;
                    foreach (var posGroupDtl in execPosGroup.ExecPosGroupDtlses)
                    {
                        posGroupDtl.ExecPosGroup = null;
                    }
                }
                return execPosGroups;
            }
        }

        public IEnumerable<ExecPosGroupDtls> SelectExecPosGroupDtls(int execPosId)
        {
            using (var db = new GERPContext())
            {
                var execPosGroupDtlses = db.ExecPosGroupDtlses.Where(o => o.ExecPosGroupId == execPosId).ToList();
                foreach (var execPosGroupDtl in execPosGroupDtlses)
                {
                    if (execPosGroupDtl.ExecPosGroup == null) continue;
                    execPosGroupDtl.ExecPosGroup.ExecPosGroupDtlses = null;
                }
                return execPosGroupDtlses;
            }
        }

        public IEnumerable<ExecutivePosition> SelectExecutivePosition()
        {
            using (var db = new GERPContext())
            {
                var executivePositions = db.ExecutivePositions.ToList();
                return executivePositions;
            }
        }

        public int InsertApprovePathDtl(int appPathId, ApproverType approverType, int? execPosGroupId, bool IsPassApproveLine,
                                        int? posId, decimal? amountMin, decimal? amountMax, bool isApproveAble, bool isForwardable, bool isRejectable,
                                        bool isPendable, bool isSendBackable, bool isLockable, bool isTakebackAble, int? createdBy)
        {
            using (var db = new GERPContext(true))
            {
                var approvePath = db.ApprovePaths.FirstOrDefault(o => o.AppPathId == appPathId);
                if (approvePath == null) throw new Exception("AppPathId not exist in table SysApprovePath");

                if (approverType == ApproverType.ExecPositionGroup && !db.ExecPosGroups.Any(o => o.ExecPosGroupId == execPosGroupId))
                    throw new OperationCanceledException("ExecPosGroupId not exist in table SysExecPosGroupId");

                if (approverType == ApproverType.Position && !db.Positions.Any(o => o.PosId == posId))
                    throw new OperationCanceledException("PosId not exist in table HrmPosition");

                var newApprovePathDtl = new ApprovePath
                    {
                        AppPathId = appPathId,
                        ApproverType = approverType,
                        ExecPosId = execPosGroupId,
                        IsPassApproveLine = IsPassApproveLine,
                        PosId = posId,
                        AppPrcId = approvePath.AppPrcId
                    };

                db.ApprovePaths.Add(newApprovePathDtl);
                db.SaveChanges();

                return newApprovePathDtl.AppPathId;
            }
        }

        public int InsertApprovePath(int appPrcId, int stepNo, int? createdBy)
        {
            if (stepNo <= 0) throw new OperationCanceledException("Step number start from 1");

            using (var db = new GERPContext(true))
            {
                if (db.ApproveProcesses.Find(appPrcId) == null)
                    throw new OperationCanceledException("Process Id not exist in table SysApproveProcess");
                if (db.ApprovePaths.FirstOrDefault(o => o.AppPrcId == appPrcId && o.StepNo == stepNo) != null)
                    throw new OperationCanceledException("There are already existed approve path with approve process id , and step no specificed");

                var newApprovePath = new ApprovePath
                    {
                        StepNo = stepNo,
                        AppPrcId = appPrcId,
                    };
                db.ApprovePaths.Add(newApprovePath);
                db.SaveChanges();

                return newApprovePath.AppPathId;
            }
        }

        public int InsertApproveProcess(string name, int appPrcGrpId, int? createdBy)
        {
            using (var db = new GERPContext(true))
            {
                if (db.ApproveProcessGroups.Find(appPrcGrpId) == null)
                    throw new OperationCanceledException("Process Group Id " + appPrcGrpId + " not exist in table SysApproveProcessGroup");
                var newApproveProcess = new ApproveProcess
                    {
                        AppPrcGrpId = appPrcGrpId,
                        Name = name,
                        CreatedBy = createdBy,
                        CreatedWhen = DateTime.Now,
                        RecordStatus = RecordStatus.UsedStatus
                    };
                db.ApproveProcesses.Add(newApproveProcess);
                db.SaveChanges();

                return newApproveProcess.AppPrcId;
            }
        }

        public int InsertApproveProcessGroup(string name, int? createdBy)
        {
            using (var db = new GERPContext(true))
            {
                var newApproveProcessGroup = new ApproveProcessGroup
                    {
                        Name = name,
                        CreatedBy = createdBy,
                        CreatedWhen = DateTime.Now,
                        RecordStatus = RecordStatus.UsedStatus
                    };
                db.ApproveProcessGroups.Add(newApproveProcessGroup);
                db.SaveChanges();

                return newApproveProcessGroup.AppPrcGrpId;
            }
        }

        public int InsertExecPosGroup(string name, int? createdBy)
        {
            using (var db = new GERPContext(true))
            {
                var newExecPosGroup = new ExecPosGroup
                    {
                        ExecPosGroupName = name,
                        CreatedBy = createdBy,
                        CreatedWhen = DateTime.Now
                    };
                db.ExecPosGroups.Add(newExecPosGroup);
                db.SaveChanges();

                return newExecPosGroup.ExecPosGroupId;
            }
        }

        public int InsertExecPosGroupDtl(int execPosGrpId, int execPosId, int? createdBy)
        {
            using (var db = new GERPContext(true))
            {
                var newExecPosGroupDtls = new ExecPosGroupDtls
                    {
                        ExecPosGroupId = execPosGrpId,
                        ExecPosId = execPosId,
                        CreatedBy = createdBy,
                        CreatedWhen = DateTime.Now
                    };
                db.ExecPosGroupDtlses.Add(newExecPosGroupDtls);
                db.SaveChanges();

                return newExecPosGroupDtls.ExecPosGroupDtlsId;
            }
        }
    }
}